package nodes;

import compiler.Compiler;
import compiler.SymbolTable;

import descriptors.AbstractDescr;
import descriptors.ConstDescr;
import descriptors.VarDescr;

public class AssignmentNode extends StatementNode {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public AssignmentNode(IdentNode ident, OperatorNode selector,ExpressionNode expression,int line, int column){
		super(line,column);
		this.ident=ident;
		this.selector=selector;
		this.expression=expression;
	}
	
	private IdentNode ident=null;
	private OperatorNode selector=null;
	private ExpressionNode expression=null;
	
	@Override
	public AbstractDescr compile(
			SymbolTable symbolTable, Compiler compiler) {
		AbstractDescr expressionDescr=expression.compile(symbolTable, compiler);
		int size=-1;
		if(expressionDescr instanceof ConstDescr) compiler.write("PUSHI, "+((ConstDescr)expressionDescr).value());
		if(ident != null){
			VarDescr descr=(VarDescr)symbolTable.search(compiler.level(), ident.ident());
			compiler.write("PUSHI, "+descr.address());
			if(descr.getLevel() == compiler.level()){
				compiler.write("GETFP");
				compiler.write("ADD");
			}
			else {
				compiler.write("PUSHI, "+descr.getLevel());
				compiler.write("GETSL");
				compiler.write("ADD");
			}
			size=descr.getSize();  //alternative: descr.type().getSize(); 
			if(descr.isVar()) compiler.write("CONT, 1");
		}
		if(selector!=null){
			AbstractDescr selectD=selector.compile(symbolTable, compiler);
			size=selectD.getSize();
		}
		compiler.write("ASSIGN, "+size);
		return null;
	}

	@Override
	public void print() {
		trace("Assignment");
		if(ident!=null) ident.print();
		if(selector!=null) selector.print();
		expression.print();
		unindent();
	}

}
